package io.renren.modules.workflow.utils;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.greenpineyu.fel.FelEngine;
import com.greenpineyu.fel.FelEngineImpl;
import com.greenpineyu.fel.context.FelContext;
import io.renren.modules.workflow.config.ICustomProcessDiagramGenerator;
import io.renren.modules.workflow.config.WorkflowConstants;
import io.renren.modules.workflow.entity.dto.ActBusProcessNode;
import org.activiti.bpmn.converter.BpmnXMLConverter;
import org.activiti.bpmn.model.Process;
import org.activiti.bpmn.model.*;
import org.activiti.engine.*;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.impl.RepositoryServiceImpl;
import org.activiti.engine.impl.TaskServiceImpl;
import org.activiti.engine.impl.interceptor.CommandExecutor;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.repository.ProcessDefinitionQuery;
import org.activiti.engine.runtime.Execution;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletResponse;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamReader;
import java.awt.*;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.io.StringReader;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Desc activiti 工具类
 * @Author landlord
 * @Date 2021/7/27 8:51
 */
@Component
public class ActBusActivitiUtils {
    private static Logger logger = LoggerFactory.getLogger(ActBusActivitiUtils.class);
    @Autowired
    private TaskService taskService;
    @Autowired
    private HistoryService historyService;
    @Autowired
    private RuntimeService runtimeService;
    @Autowired
    private RepositoryService repositoryService;
    @Autowired
    private ProcessEngine processEngine;

    //把部署流程转换XML 字符串
    public String getBpmnXml(String processDefId) {
        BpmnModel model = repositoryService.getBpmnModel(processDefId);
        if (model != null && model.getLocationMap().size() > 0) {
            BpmnXMLConverter converter = new BpmnXMLConverter();
            //把bpmnModel对象转换成字符
            byte[] bytes = converter.convertToXML(model);
            String xmlContenxt = new String(bytes);
            return xmlContenxt;
        }
        return null;
    }

    //根据流程bpmnXml获取流程中所有的流程变量key集合
    public Set<String> getBpmnXmlAllVariables(String bpmnXml) {
        XMLInputFactory factory = XMLInputFactory.newFactory();
        Reader reader = new StringReader(bpmnXml);
        XMLStreamReader streamReader = null;
        try {
            streamReader = factory.createXMLStreamReader(reader);
            BpmnXMLConverter converter = new BpmnXMLConverter();
            BpmnModel bpmnModel = converter.convertToBpmnModel(streamReader);
            Collection<FlowElement> flowElements = bpmnModel.getMainProcess().getFlowElements();
            List<String> euls = new ArrayList<>();
            for (FlowElement e : flowElements) {
                if (e instanceof SequenceFlow) {
                    SequenceFlow sequenceFlow = (SequenceFlow) e;
                    String ce = sequenceFlow.getConditionExpression();
                    if (ObjectUtil.isNotNull(ce)) {
                        euls.add(ce);
                    }
                }
            }
            Set<String> resList = new HashSet<>();
            if (euls != null && euls.size() > 0) {
                for (String str : euls) {
                    String ex = getVariableNameByExpression(str);
                    resList.add(ex.split(" ")[0]);
                }
            }
            return resList;
        } catch (Exception e) {
            logger.error(e.getMessage());
            return null;
        }
    }

    //获取Process对象
    public Process getProcess(String processDefId){
        BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefId);
        return bpmnModel.getProcesses().get(0);
    }
    //根据ID查询流程节点对象, 如果是子任务，则返回子任务的开始节点
    public FlowElement getFlowElementById(String id,Collection<FlowElement> flowElements){
        for (FlowElement flowElement : flowElements) {
            if (flowElement.getId().equals(id)) {
                //如果是子任务，则查询出子任务的开始节点
                if (flowElement instanceof SubProcess) {
                    return getStartFlowElement(((SubProcess) flowElement).getFlowElements());
                }
                return flowElement;
            }
            if (flowElement instanceof SubProcess) {
                FlowElement flowElement1 = getFlowElementById(id, ((SubProcess) flowElement).getFlowElements());
                if (flowElement1 != null) {
                    return flowElement1;
                }
            }
        }
        return null;
    }
   //返回流程的开始节点
    public  FlowElement getStartFlowElement(Collection<FlowElement> flowElements) {
        for (FlowElement flowElement : flowElements) {
            if (flowElement instanceof StartEvent) {
                return flowElement;
            }
        }
        return null;
    }

    /**
     * 查询下一步节点 递归
     *
     * @param flowElements 全流程节点集合
     * @param flowElement  当前节点
     * @param map          业务数据
     * @param nextUser     下一步用户节点
     */
    public void getNextNodeRecur(Collection<FlowElement> flowElements, FlowElement flowElement, Map<String, Object> map, List<UserTask> nextUser) {

        //如果是结束节点
        if (flowElement instanceof EndEvent) {

            //如果是子任务的结束节点
            if (getSubProcess(flowElements, flowElement) != null) {
                flowElement = getSubProcess(flowElements, flowElement);
            }else {
                UserTask userTask = new UserTask();
                userTask.setName("_END_");
                nextUser.add(userTask);
                return;
            }
        }

        //获取Task的出线信息--可以拥有多个
        List<SequenceFlow> outGoingFlows = null;
        if (flowElement instanceof Task) {
            outGoingFlows = ((org.activiti.bpmn.model.Task) flowElement).getOutgoingFlows();
        } else if (flowElement instanceof Gateway) {
            outGoingFlows = ((Gateway) flowElement).getOutgoingFlows();
        } else if (flowElement instanceof StartEvent) {
            outGoingFlows = ((StartEvent) flowElement).getOutgoingFlows();
        } else if (flowElement instanceof SubProcess) {
            outGoingFlows = ((SubProcess) flowElement).getOutgoingFlows();
        } else if (flowElement instanceof UserTask) {
            outGoingFlows = ((UserTask) flowElement).getOutgoingFlows();
        }

        if (outGoingFlows != null && outGoingFlows.size() > 0) {
            //遍历所有的出线--找到可以正确执行的那一条
            for (SequenceFlow sequenceFlow : outGoingFlows) {

                //1.有表达式，且为true
                //2.无表达式
                String expression = sequenceFlow.getConditionExpression();
                if (StrUtil.isBlank(expression) ||
                        Boolean.parseBoolean(
                                String.valueOf(
                                       result(map, expression.substring(expression.lastIndexOf("{") + 1, expression.lastIndexOf("}")))))) {
                    //出线的下一节点
                    String nextFlowElementID = sequenceFlow.getTargetRef();
                    //查询下一节点的信息
                    FlowElement nextFlowElement = getFlowElementById(nextFlowElementID, flowElements);

                    //用户任务
                    if (nextFlowElement instanceof UserTask) {
                        nextUser.add((UserTask) nextFlowElement);
                    }
                    //排他网关
                    else if (nextFlowElement instanceof ExclusiveGateway) {
                        getNextNodeRecur(flowElements, nextFlowElement, map, nextUser);
                    }
                    //并行网关
                    else if (nextFlowElement instanceof ParallelGateway) {
                        getNextNodeRecur(flowElements, nextFlowElement, map, nextUser);
                    }
                    //接收任务
                    else if (nextFlowElement instanceof ReceiveTask) {
                        getNextNodeRecur(flowElements, nextFlowElement, map, nextUser);
                    }
                    //子任务的起点
                    else if (nextFlowElement instanceof StartEvent) {
                        getNextNodeRecur(flowElements, nextFlowElement, map, nextUser);
                    }
                    //结束节点
                    else if (nextFlowElement instanceof EndEvent) {
                        getNextNodeRecur(flowElements, nextFlowElement, map, nextUser);
                    }
                }
            }
        }
    }
    /**
     * 查询一个节点的是否子任务中的节点，如果是，返回子任务
     * @param flowElements 全流程的节点集合
     * @param flowElement  当前节点
     */
    public FlowElement getSubProcess(Collection<FlowElement> flowElements, FlowElement flowElement) {
        for (FlowElement fel : flowElements) {
            if (fel instanceof SubProcess) {
                for (FlowElement flowElement2 : ((SubProcess) fel).getFlowElements()) {
                    if (flowElement.equals(flowElement2)) {
                        return fel;
                    }
                }
            }
        }
        return null;
    }

    //解析el表达式
    public  Object result(Map<String,Object> map,String expression){
        if(StrUtil.isEmpty(expression)){
            return false;
        }
        FelEngine fel = new FelEngineImpl();
        FelContext ctx = fel.getContext();
        for (Map.Entry<String, Object> entry : map.entrySet()) {
            ctx.set(entry.getKey(),entry.getValue());
        }
        return fel.eval(expression);
    }

    //获取出流程跟踪流程图
    public void traceProcessFlowImg(String pProcessInstanceId, HttpServletResponse response) throws Exception{
            if (StrUtil.isEmpty(pProcessInstanceId)) {
                return;
            }
            String processDefinitionId = "";
            ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(pProcessInstanceId).singleResult();
            if (processInstance == null) {
                HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(pProcessInstanceId).singleResult();
                processDefinitionId = historicProcessInstance.getProcessDefinitionId();
            } else {
                processDefinitionId = processInstance.getProcessDefinitionId();
            }
            ProcessDefinitionQuery pdq = repositoryService.createProcessDefinitionQuery();
            ProcessDefinition pd = pdq.processDefinitionId(processDefinitionId).singleResult();

            String resourceName = pd.getDiagramResourceName();

            if (resourceName.endsWith(".png") && StrUtil.isEmpty(pProcessInstanceId) == false) {
                getActivitiProccessImage(pProcessInstanceId, response);
            } else {
                // 通过接口读取
                InputStream resourceAsStream = repositoryService.getResourceAsStream(pd.getDeploymentId(), resourceName);
                // 输出资源内容到相应对象
                byte[] b = new byte[1024];
                int len = -1;
                while ((len = resourceAsStream.read(b, 0, 1024)) != -1) {
                    response.getOutputStream().write(b, 0, len);
                }
            }
        }

    /**
     * 获取流程图像，已执行节点和流程线高亮显示
     */

    public void getActivitiProccessImage(String pProcessInstanceId, HttpServletResponse response) {
        try {
            //  获取历史流程实例
            HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery()
                    .processInstanceId(pProcessInstanceId).singleResult();

            if (historicProcessInstance == null) {
               throw new Exception("获取流程实例ID[" + pProcessInstanceId + "]对应的历史流程实例失败！");
            } else {
                // 获取流程定义
                ProcessDefinitionEntity processDefinition = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService)
                        .getDeployedProcessDefinition(historicProcessInstance.getProcessDefinitionId());

                // 获取流程历史中已执行节点，并按照节点在流程中执行先后顺序排序
                List<HistoricActivityInstance> historicActivityInstanceList = historyService.createHistoricActivityInstanceQuery()
                        .processInstanceId(pProcessInstanceId).orderByHistoricActivityInstanceId().asc().list();

                // 已执行的节点ID集合
                List<String> executedActivityIdList = new ArrayList<String>();
                int index = 1;
                //logger.info("获取已经执行的节点ID");
                for (HistoricActivityInstance activityInstance : historicActivityInstanceList) {
                    executedActivityIdList.add(activityInstance.getActivityId());
                    index++;
                }

                BpmnModel bpmnModel = repositoryService.getBpmnModel(historicProcessInstance.getProcessDefinitionId());

                // 已执行的线集合
                List<String> flowIds = new ArrayList<String>();
                // 获取流程走过的线 (getHighLightedFlows是下面的方法)
                flowIds = getHighLightedFlows(bpmnModel, processDefinition, historicActivityInstanceList);
                Set<String> currIds = runtimeService.createExecutionQuery().processInstanceId(pProcessInstanceId).list()
                        .stream().map(e -> e.getActivityId()).collect(Collectors.toSet());
                ICustomProcessDiagramGenerator diagramGenerator = (ICustomProcessDiagramGenerator) processEngine.getProcessEngineConfiguration().getProcessDiagramGenerator();
                InputStream imageStream = diagramGenerator.generateDiagram(bpmnModel, "png", executedActivityIdList,
                        flowIds, "宋体", "宋体", "宋体", null, 1.0, new Color[]{WorkflowConstants.COLOR_NORMAL, WorkflowConstants.COLOR_CURRENT}, currIds);
                response.setContentType("image/png");
                OutputStream os = response.getOutputStream();
                int bytesRead = 0;
                byte[] buffer = new byte[8192];
                while ((bytesRead = imageStream.read(buffer, 0, 8192)) != -1) {
                    os.write(buffer, 0, bytesRead);
                }
                os.close();
                imageStream.close();
            }
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
    }

    private List<String> getHighLightedFlows(BpmnModel bpmnModel, ProcessDefinitionEntity processDefinitionEntity, List<HistoricActivityInstance> historicActivityInstances) {
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); //24小时制
        List<String> highFlows = new ArrayList<String>();// 用以保存高亮的线flowId
        for (int i = 0; i < historicActivityInstances.size() - 1; i++) {
            // 对历史流程节点进行遍历
            // 得到节点定义的详细信息
            FlowNode activityImpl = (FlowNode) bpmnModel.getMainProcess().getFlowElement(historicActivityInstances.get(i).getActivityId());


            List<FlowNode> sameStartTimeNodes = new ArrayList<FlowNode>();// 用以保存后续开始时间相同的节点
            FlowNode sameActivityImpl1 = null;

            HistoricActivityInstance activityImpl_ = historicActivityInstances.get(i);// 第一个节点
            HistoricActivityInstance activityImp2_;

            for (int k = i + 1; k <= historicActivityInstances.size() - 1; k++) {
                activityImp2_ = historicActivityInstances.get(k);// 后续第1个节点

                if (activityImpl_.getActivityType().equals("userTask") && activityImp2_.getActivityType().equals("userTask") &&
                        df.format(activityImpl_.getStartTime()).equals(df.format(activityImp2_.getStartTime()))) //都是usertask，且主节点与后续节点的开始时间相同，说明不是真实的后继节点
                {

                } else {
                    sameActivityImpl1 = (FlowNode) bpmnModel.getMainProcess().getFlowElement(historicActivityInstances.get(k).getActivityId());//找到紧跟在后面的一个节点
                    break;
                }

            }
            sameStartTimeNodes.add(sameActivityImpl1); // 将后面第一个节点放在时间相同节点的集合里
            for (int j = i + 1; j < historicActivityInstances.size() - 1; j++) {
                HistoricActivityInstance activityImpl1 = historicActivityInstances.get(j);// 后续第一个节点
                HistoricActivityInstance activityImpl2 = historicActivityInstances.get(j + 1);// 后续第二个节点

                if (df.format(activityImpl1.getStartTime()).equals(df.format(activityImpl2.getStartTime()))) {// 如果第一个节点和第二个节点开始时间相同保存
                    FlowNode sameActivityImpl2 = (FlowNode) bpmnModel.getMainProcess().getFlowElement(activityImpl2.getActivityId());
                    sameStartTimeNodes.add(sameActivityImpl2);
                } else {// 有不相同跳出循环
                    break;
                }
            }
            List<SequenceFlow> pvmTransitions = activityImpl.getOutgoingFlows(); // 取出节点的所有出去的线

            for (SequenceFlow pvmTransition : pvmTransitions) {// 对所有的线进行遍历
                FlowNode pvmActivityImpl = (FlowNode) bpmnModel.getMainProcess().getFlowElement(pvmTransition.getTargetRef());// 如果取出的线的目标节点存在时间相同的节点里，保存该线的id，进行高亮显示
                if (sameStartTimeNodes.contains(pvmActivityImpl)) {
                    highFlows.add(pvmTransition.getId());
                }
            }

        }
        return highFlows;

    }


    //通过表达式获取其中的变量名
    public String getVariableNameByExpression(String expression) {
        return expression.replace("${", "")
                .replace("}", "");
    }

    /**************************************************************************************
     *  任务 封装 区域
     * ***********************************************************************************/
    //根据任务ID获取活动任务对象
    public Task getTaskByTaskId(String taskId) {
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        return task;
    }

    //根据任务ID获取历史任务对象
    public HistoricTaskInstance getHistoricTaskById(String taskId) {
        HistoricTaskInstance historicTaskInstance =
                historyService.createHistoricTaskInstanceQuery().taskId(taskId).singleResult();
        return historicTaskInstance;
    }

    /**************************************************************************************
     *  流程办理 封装 区域
     * ***********************************************************************************/
    //设置任务环节办理人
    public void setAssignTask(String taskId, String assignName) {
        Task task = getTaskByTaskId(taskId);
        taskService.setAssignee(task.getId(), assignName);
    }

    //任务办理
    public void comoleteByVariables(String taskId, Map<String, Object> vars,boolean localScope) {
        taskService.complete(taskId, vars,localScope);
    }

    //添加审批意见
    public void addComment(Task task, String comment) {
        taskService.addComment(task.getId(), task.getProcessInstanceId(), comment);
    }
    //根据任务ID获取当前任务对象
    public Task getCurrentTaskOrCurrentUserTaks(String taskId,String userId){
        if(StrUtil.isEmpty(userId)){
            return taskService.createTaskQuery().taskId(taskId).singleResult();
        }else{
            return taskService.createTaskQuery().taskId(taskId).taskAssignee(userId).singleResult();
        }
    }
    ///根据任务ID获取流程变量
    public Map<String,Object> getTaskVariables(String taskId){
        Map<String,Object> resMap = taskService.getVariables(taskId);
        return resMap;
    }
    /**
     * 节点跳转
     * @param taskId 当前任务ID
     * @param targetNodeId 目标节点定义ID
     * @param assignee 审批用户
     * @param variables 流转数据
     * @param comment 备注/意见
     */
    public void nodeJumpTo(String taskId, String targetNodeId, String assignee, Map<String, Object> variables, String comment) {
        CommandExecutor commandExecutor = ((TaskServiceImpl) taskService).getCommandExecutor();
        commandExecutor.execute(new ActBusJumpAnyWhereCmd(taskId, targetNodeId, assignee, variables, comment));
    }

    /**
     * 获取所有可驳回的节点列表
     * @param currentNodeId 当前节点ID
     * @param processDefId 流程定义ID
     * @return List<ProcessNode>
     */
    public  List<ActBusProcessNode> getCanBackNodes(String currentNodeId, String processDefId) {
        List<ActBusProcessNode> canBackNodes = new ArrayList<>();
        getIncomeNodesRecur(currentNodeId, processDefId, canBackNodes, true, currentNodeId);
        for (int i = 0; i < canBackNodes.size(); i++) {
            List<HistoricActivityInstance> historicActivityInstances = historyService.createHistoricActivityInstanceQuery()
                    .processDefinitionId(processDefId).activityId(canBackNodes.get(i).getNodeId()).finished().list();
            if (CollectionUtil.isEmpty(historicActivityInstances)) {
                canBackNodes.remove(i);
                i--;
            }
        }
        return canBackNodes;
    }

    //获取审批节点集合
    public void getIncomeNodesRecur(String currentNodeId, String processDefId, List<ActBusProcessNode> incomeNodes, boolean isAll, String originalCurrentNodeId) {
        getIncomeNodesRecur(currentNodeId, processDefId, incomeNodes, isAll, true, originalCurrentNodeId);
    }

    //递归获取审批节点集合
    public  void getIncomeNodesRecur(String currentNodeId, String processDefId, List<ActBusProcessNode> incomeNodes, boolean isAll, boolean isFirstExec, String originalCurrentNodeId) {
        Process process = getProcess(processDefId);
        if (!isFirstExec) {
            if (currentNodeId.equals(originalCurrentNodeId)) {
                return;
            }
        }
        FlowElement currentFlowElement = process.getFlowElement(currentNodeId);
        List<SequenceFlow> incomingFlows = null;
        if (currentFlowElement instanceof UserTask) {
            incomingFlows = ((UserTask) currentFlowElement).getIncomingFlows();
        } else if (currentFlowElement instanceof Gateway) {
            incomingFlows = ((Gateway) currentFlowElement).getIncomingFlows();
        } else if (currentFlowElement instanceof StartEvent) {
            incomingFlows = ((StartEvent) currentFlowElement).getIncomingFlows();
        }
        if (incomingFlows != null && incomingFlows.size() > 0) {
            incomingFlows.forEach(incomingFlow -> {
                String expression = incomingFlow.getConditionExpression();
                // 出线的上一节点
                String sourceFlowElementID = incomingFlow.getSourceRef();
                // 查询上一节点的信息
                FlowElement preFlowElement = process.getFlowElement(sourceFlowElementID);

                //用户任务
                if (preFlowElement instanceof UserTask) {
                    incomeNodes.add(new ActBusProcessNode(preFlowElement.getId(), preFlowElement.getName()));
                    if (isAll) {
                        getIncomeNodesRecur(preFlowElement.getId(), processDefId, incomeNodes, true, false, originalCurrentNodeId);
                    }
                }
                //排他网关
                else if (preFlowElement instanceof ExclusiveGateway) {
                    getIncomeNodesRecur(preFlowElement.getId(), processDefId, incomeNodes, isAll, false, originalCurrentNodeId);
                }
                //并行网关
                else if (preFlowElement instanceof ParallelGateway) {
                    getIncomeNodesRecur(preFlowElement.getId(), processDefId, incomeNodes, isAll, false, originalCurrentNodeId);
                }
            });
        }
    }

    //任务驳回上一环节
    public void dismissedOnALink(String taskId, Map<String, Object> vars) throws Exception {
        List<Map<String, String>> incomeNodes = new ArrayList<>();
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        if (task == null) {
            throw new Exception("任务驳回失败:当前任务已经被处理");
        }
        String processInstanceId = task.getProcessInstanceId();
        // 取得所有历史任务按时间降序排序
        List<HistoricTaskInstance> htiList = historyService.createHistoricTaskInstanceQuery()
                .processInstanceId(processInstanceId)
                .orderByTaskCreateTime()
                .desc()
                .list();
        if (ObjectUtil.isNull(htiList) || htiList.size() < 2) {
            return;
        }
        // list里的第二条代表上一个任务
        HistoricTaskInstance lastTask = htiList.get(1);
        // list里第一条代表当前任务
        HistoricTaskInstance curTask = htiList.get(0);

        String currActivityId = curTask.getTaskDefinitionKey();
        //获取当前任务节点
        BpmnModel bpmnModel = repositoryService.getBpmnModel(task.getProcessDefinitionId());
        Process process = bpmnModel.getProcesses().get(0);

        getIncomeNodesRecur(currActivityId, incomeNodes, process, false);

        FlowNode currFlow = (FlowNode) bpmnModel.getMainProcess().getFlowElement(currActivityId);
        if (currFlow == null) {
            List<SubProcess> subProcessList = bpmnModel.getMainProcess().findFlowElementsOfType(SubProcess.class, true);
            for (SubProcess subProcess : subProcessList) {
                FlowElement flowElement = subProcess.getFlowElement(currActivityId);
                if (flowElement != null) {
                    currFlow = (FlowNode) flowElement;
                    break;
                }
            }
        }

        // 记录原活动方向
        List<SequenceFlow> oriSequenceFlows = new ArrayList<>();
        oriSequenceFlows.addAll(currFlow.getOutgoingFlows());

        // 清理活动方向
        currFlow.getOutgoingFlows().clear();

        List<SequenceFlow> newSequenceFlows = new ArrayList<>();

        for (int i = 0; i < incomeNodes.size(); i++) {
            Map<String, String> item = incomeNodes.get(i);
            String nodeId = item.get("id");
            // 获取目标节点
            FlowNode target = (FlowNode) bpmnModel.getFlowElement(nodeId);
            //如果不是同一个流程（子流程）不能驳回
            if (!(currFlow.getParentContainer().equals(target.getParentContainer()))) {
                continue;
            }
            // 建立新方向
            SequenceFlow newSequenceFlow = new SequenceFlow();
            String uuid = UUID.randomUUID().toString().replace("-", "");
            newSequenceFlow.setId(uuid);
            newSequenceFlow.setSourceFlowElement(currFlow);// 原节点
            newSequenceFlow.setTargetFlowElement(target);// 目标节点
            newSequenceFlows.add(newSequenceFlow);
        }
        ;
        currFlow.setOutgoingFlows(newSequenceFlows);
        // 拒接、通过、驳回指定节点
        taskService.complete(taskId, vars);
        //恢复原方向
        currFlow.setOutgoingFlows(oriSequenceFlows);
        Task nextTask = taskService
                .createTaskQuery().processInstanceId(processInstanceId).singleResult();
        // 设置执行人
        if (nextTask != null) {
            taskService.setAssignee(nextTask.getId(), lastTask.getAssignee());
        }
    }

    //递归遍历获取上个任务节点
    public void getIncomeNodesRecur(String currentNodeId, List<Map<String, String>> incomeNodes,
                                    Process process, boolean isAll) {
        FlowElement currentFlowElement = process.getFlowElement(currentNodeId);
        List<SequenceFlow> incomingFlows = null;
        if (currentFlowElement instanceof UserTask) {
            incomingFlows = ((UserTask) currentFlowElement).getIncomingFlows();
        } else if (currentFlowElement instanceof Gateway) {
            incomingFlows = ((Gateway) currentFlowElement).getIncomingFlows();
        } else if (currentFlowElement instanceof StartEvent) {
            incomingFlows = ((StartEvent) currentFlowElement).getIncomingFlows();
        }
        if (incomingFlows != null && incomingFlows.size() > 0) {
            incomingFlows.forEach(incomingFlow -> {
                String expression = incomingFlow.getConditionExpression();
                // 出线的上一节点
                String sourceFlowElementID = incomingFlow.getSourceRef();
                // 查询上一节点的信息
                FlowElement preFlowElement = process.getFlowElement(sourceFlowElementID);
                //用户任务
                if (preFlowElement instanceof UserTask) {
                    Map<String, String> tempMap = new HashMap<>();
                    tempMap.put("id", preFlowElement.getId());
                    tempMap.put("name", preFlowElement.getName());
                    incomeNodes.add(tempMap);
                    if (isAll) {
                        getIncomeNodesRecur(preFlowElement.getId(), incomeNodes, process, true);
                    }
                }
                //排他网关
                else if (preFlowElement instanceof ExclusiveGateway) {
                    getIncomeNodesRecur(preFlowElement.getId(), incomeNodes, process, isAll);
                }
                //并行网关
                else if (preFlowElement instanceof ParallelGateway) {
                    getIncomeNodesRecur(preFlowElement.getId(), incomeNodes, process, isAll);
                }
            });
        }
    }

    //任务驳回方式二
    public void taskReject(String taskId, Map<String, Object> vars) throws Exception {
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        String processInstanceId = task.getProcessInstanceId();
        // 取得所有历史任务按时间降序排序
        List<HistoricTaskInstance> htiList = historyService.createHistoricTaskInstanceQuery()
                .processInstanceId(processInstanceId)
                .orderByTaskCreateTime()
                .desc()
                .list();
        if (ObjectUtil.isNull(htiList) || htiList.size() < 2) {
            return;
        }
        // list里的第二条代表上一个任务
        HistoricTaskInstance lastTask = htiList.get(1);
        // list里第一条代表当前任务
        HistoricTaskInstance curTask = htiList.get(0);
        // 当前节点的executionId
        String curExecutionId = curTask.getExecutionId();
        // 上个节点的taskId
        String lastTaskId = lastTask.getId();
        // 上个节点的executionId
        String lastExecutionId = lastTask.getExecutionId();
        if (null == lastTaskId) {
            throw new Exception("LAST TASK IS NULL");
        }
        String processDefinitionId = lastTask.getProcessDefinitionId();
        BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
        String lastActivityId = null;
        List<HistoricActivityInstance> haiFinishedList = historyService.createHistoricActivityInstanceQuery()
                .executionId(lastExecutionId).finished().list();
        for (HistoricActivityInstance hai : haiFinishedList) {
            if (lastTaskId.equals(hai.getTaskId())) {
                // 得到ActivityId，只有HistoricActivityInstance对象里才有此方法
                lastActivityId = hai.getActivityId();
                break;
            }
        }

        // 得到上个节点的信息
        FlowNode lastFlowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(lastActivityId);
        // 取得当前节点的信息
        Execution execution = runtimeService.createExecutionQuery().executionId(curExecutionId).singleResult();
        String curActivityId = execution.getActivityId();
        FlowNode curFlowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(curActivityId);
        //记录当前节点的原活动方向
        List<SequenceFlow> oriSequenceFlows = new ArrayList<>();
        oriSequenceFlows.addAll(curFlowNode.getOutgoingFlows());
        //清理活动方向
        curFlowNode.getOutgoingFlows().clear();
        //建立新方向
        List<SequenceFlow> newSequenceFlowList = new ArrayList<>();
        SequenceFlow newSequenceFlow = new SequenceFlow();
        newSequenceFlow.setId("newSequenceFlowId");
        newSequenceFlow.setSourceFlowElement(curFlowNode);
        newSequenceFlow.setTargetFlowElement(lastFlowNode);
        newSequenceFlowList.add(newSequenceFlow);
        curFlowNode.setOutgoingFlows(newSequenceFlowList);
        // 完成任务
        taskService.complete(task.getId(), vars);
        //恢复原方向
        curFlowNode.setOutgoingFlows(oriSequenceFlows);
        Task nextTask = taskService
                .createTaskQuery().processInstanceId(processInstanceId).singleResult();
        // 设置执行人
        if (nextTask != null) {
            taskService.setAssignee(nextTask.getId(), lastTask.getAssignee());
        }
    }

}
